package my.design.mode.singleton;

/**
 * 双重锁错误写法
 * @author xsw
 * @date 2018年11月1日
 */
public class DCLExampleError {
	//懒汉模式，当需要使用这个对象时，才进行对象初始化
	private static DCLExampleError intance;
	
	private DCLExampleError(){}
	
	/**
	 * 双重锁这个理论是没问题的，只是在java中由于指令重排序会出先错误。<br/>
	 * 理论上，两个线程 a和b同时进入 1 时，到 2 遇上同步关键词，只能有一个进入，假设是a<br/>
	 * a 进入2，在 3 中判断为null，创建 instance，退出同步锁定。<br/>
	 * b 进入2，在 3 中判断不为null，直接退出。程序正常。<br/>
	 * <br/>
	 * 4 这个步骤不是原子操作，它可以才分成以下 3 步：
	 * 1. 创建内存空间
	 * 2. 初始化对象
	 * 3. 将对象指向刚分配好的内存空间
	 * 指令重排序后就可能是这样的顺序：1->3->2。在没有初始化对象的时候，就向对象指针指向刚才分配好的内存空间。
	 * 结果：上面连个线程返回了两个不一样的对象。
	 * @return
	 */
	public static DCLExampleError getInstance(){
		if(intance == null){// 1
			synchronized (DCLExampleError.class) {//2
				if(intance == null){//3
					intance = new DCLExampleError();//4
				}
			}
		}
		return intance;//5
	}
}
